import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

public class Level1 implements Runnable{
    private int enemyX;
    private int enemyY;
    private Thread runner;
    private LayerManager manager;
    private static EnemySprite[][] enemySprite = new EnemySprite[3][5];
    private Sprite[][] expSprite = new Sprite[3][5];
    private int[][] expFrame = new int[3][5];
    private Sprite[] fBulletSprite = new Sprite[60];
    private Sprite bonusSprite;
    private Image enemyImage1;
    private Image enemyImage2;
    private Image enemyImage3;
    private Image bonusImage;
    private FighterCanvas parent;
    private int time;
    private int enemyCounter = 0;
    private int aTime = 100;
    private int bTime = 100;
    private int cTime = 100;
    private int dTime = 100;
    private int eTime = 100;
    private int aHeight = 200;
    private int bHeight = 200;
    private int cHeight = 200;
    private int dHeight = 200;
    private int eHeight = 200;
    private Image expImage;
    private int waveTime;
    private int[] enemyHits = {0,0,0};
    private int bonusX = 300;

    public Level1(FighterCanvas parent){
        this.parent = parent;
        this.manager = parent.getManager();
    }

    public void start(){
        //load image
        try{
            enemyImage1 = Image.createImage("/enemy4.png");
            enemyImage2 = Image.createImage("/enemy5.png");
            enemyImage3 = Image.createImage("/boss1.png");
            expImage = Image.createImage("/exp2.png");
            bonusImage = Image.createImage("/bonus.png");

        } catch(Exception e) {System.err.println(e); return; }

        //start thread to display bullets
        runner = new Thread(this);
        runner.start();
    }

    public void run() {
        try {
            for(int i=0; i<3; i++){
                for(int t=0; t<5; t++){
                    enemySprite[i][t] = new EnemySprite(enemyImage1, 34, 13);
                    expSprite[i][t] = new Sprite(expImage, 20, 20);
                    expFrame[i][t] = 20;
                }
            }
            bonusSprite = new Sprite(bonusImage, 14, 14);
            
            while(true){
                this.time = parent.time;

                if(time < 580){
                    wave1(0, enemyImage1, 1);
                    waveTime = time;
                }else if(time < 1130){
                    wave1(1, enemyImage2, 1);
                    waveTime = time - 540;
                }else if(time < 1680){
                    wave1(0, enemyImage1, 2);
                    waveTime = time - 1090;
                }else if(time < 2230){
                    wave1(1, enemyImage2, 2);
                    waveTime = time - 1640;
                }
                moveBonus();

              //wait before creating another one
              Thread.currentThread().sleep(15);

            }
        } catch(Exception e) {System.err.println(e);}
    }

    private void wave1(int planeType, Image eImage, int enemySpeed){
        //first wave variables already preset - top all in a row
         if(waveTime == 59){
            enemyCounter = 0;
            visible();
            aTime = 60; bTime = 70; cTime = 80; dTime = 90; eTime = 100;
            aHeight = 50; bHeight = 150; cHeight = 80; dHeight = 120; eHeight = 50;
        }

        //set variables for second wave - bottom all in a row
        if(waveTime == 104){
            enemyCounter = 0;
            visible();
            aTime = 105; bTime = 115; cTime = 125; dTime = 135;
            aHeight = 150; bHeight = 80; cHeight = 120; dHeight = 80;
        }
        
        //set variables for third wave - top row fly down
        if(waveTime == 154){
            visible();
            enemyCounter = 0;
            aTime = 155; bTime = 165; cTime = 175; dTime = 185;
            aHeight = 50; bHeight = 50; cHeight = 50; dHeight = 50;
        }

        //set variables for fourth wave - bottom row fly up
        if(waveTime == 204){
            enemyCounter = 0;
            visible();
            aTime = 205; bTime = 215; cTime = 225; dTime = 235;
            aHeight = 150; bHeight = 150; cHeight = 150; dHeight = 150;
        }
        
        //set variables for fifth wave - staggered from top down
        if(waveTime == 259){
            enemyCounter = 0;
            visible();
            aTime = 260; bTime = 265; cTime = 270; dTime = 275; eTime = 280;
            aHeight = 170; bHeight = 137; cHeight = 105; dHeight = 72; eHeight = 40;
        }

        //set variables for sixth wave - wall of planes
        if(waveTime == 304){
            enemyCounter = 0;
            visible();
            aTime = 305; bTime = 305; cTime = 305; dTime = 305; eTime = 305;
            aHeight = 40; bHeight = 72; cHeight = 105; dHeight = 137; eHeight = 170;
        }

         //set variables for seventh wave - staggered from bottom
        if(waveTime == 324){
            enemyCounter = 0;
            visible();
            aTime = 330; bTime = 335; cTime = 340; dTime = 345; eTime = 350;
            aHeight = 170; bHeight = 137; cHeight = 105; dHeight = 72; eHeight = 40;
        }

        //set variables for eigth wave - wall of planes
        if(waveTime == 374){
            enemyCounter = 0;
            visible();
            aTime = 375; bTime = 375; cTime = 375; dTime = 375; eTime = 375;
            aHeight = 40; bHeight = 72; cHeight = 105; dHeight = 137; eHeight = 170;
        }

        //set variables for eigth wave - wall of planes
        if(waveTime == 399){
            enemyCounter = 0;
            visible();
            aTime = 400; bTime = 410; cTime = 420; dTime = 430; eTime = 440;
            aHeight = 50; bHeight = 150; cHeight = 50; dHeight = 150;eHeight = 50;
        }

         if(waveTime == 457){
             enemyCounter = 0;
         }

        //boss sprite
        if(waveTime == 458){
            if(enemyCounter ==0){
                enemySprite[2][planeType] = new EnemySprite(enemyImage3, 45, 19);
                enemySprite[2][planeType].defineReferencePixel(1, 7);
                enemySprite[2][planeType].setPosition(125, 75);
                manager.insert(enemySprite[2][planeType], 0);
                enemyCounter++;
            }
        }
        //movement for boss sprite
        if(waveTime > 458 && waveTime < 460){
            enemySprite[2][planeType].forward(enemySprite[2][planeType], 1);
        }
        if(waveTime > 460 && waveTime < 465){
            enemySprite[2][planeType].up(enemySprite[2][planeType], 1);
        }
        if(waveTime > 465 && waveTime < 485){
            enemySprite[2][planeType].down(enemySprite[2][planeType], 1);
        }
        if(waveTime > 485 && waveTime < 504){
            enemySprite[2][planeType].forwardDiagUp(enemySprite[2][planeType], 1);
        }
        if(waveTime > 504 && waveTime < 524){
            enemySprite[2][planeType].down(enemySprite[2][planeType], 1);
        }
        if(waveTime > 524 && waveTime < 543){
            enemySprite[2][planeType].backDiagUp(enemySprite[2][planeType], 1);
        }
        if(waveTime > 543 && waveTime < 553){
            enemySprite[2][planeType].down(enemySprite[2][planeType], 1);
        }
        if(waveTime > 553 && waveTime < 603){
            enemySprite[2][planeType].forward(enemySprite[2][planeType], 1);
        }
        //creates sprite at timed increments
        if(waveTime == aTime){
            if(enemyCounter == 0){
                enemySprite[planeType][0] = new EnemySprite(eImage, 34, 13);
                enemySprite[planeType][0].defineReferencePixel(1, 7);
                enemySprite[planeType][0].setPosition(137, aHeight);
                manager.insert(enemySprite[planeType][0], 0);
                enemyCounter = 1;
            }
        }
        if(waveTime == bTime){
            if(enemyCounter == 1){
                enemySprite[planeType][1] = new EnemySprite(eImage, 34, 13);
                enemySprite[planeType][1].defineReferencePixel(1, 7);
                enemySprite[planeType][1].setPosition(137, bHeight);
                manager.insert(enemySprite[planeType][1], 0);
                enemyCounter = 2;
            }
        }
        if(waveTime == cTime){
            if(enemyCounter == 2){
                enemySprite[planeType][2] = new EnemySprite(eImage, 34, 13);
                enemySprite[planeType][2].defineReferencePixel(1, 7);
                enemySprite[planeType][2].setPosition(137, cHeight);
                manager.insert(enemySprite[planeType][2], 0);
                enemyCounter = 3;
            }
        }
        if(waveTime == dTime){
            if(enemyCounter == 3){
                enemySprite[planeType][3] = new EnemySprite(eImage, 34, 13);
                enemySprite[planeType][3].defineReferencePixel(1, 7);
                enemySprite[planeType][3].setPosition(137, dHeight);
                manager.insert(enemySprite[planeType][3], 0);
                enemyCounter = 4;
            }
        }

        if(waveTime == eTime){
            if(enemyCounter == 4){
                enemySprite[planeType][4] = new EnemySprite(eImage, 34, 13);
                enemySprite[planeType][4].defineReferencePixel(1, 7);
                enemySprite[planeType][4].setPosition(137, eHeight);
                manager.insert(enemySprite[planeType][4], 0);
                enemyCounter = 5;
            }
        }

        //move each sprite
        for(int t=0; t<5; t++){
            if(waveTime < 160){
                enemySprite[planeType][t].forward(enemySprite[planeType][t], enemySpeed);
            }
            else{
                if(enemySprite[planeType][t].getX()>100){
                    enemySprite[planeType][t].forward(enemySprite[planeType][t], enemySpeed);
                }else{
                    if(waveTime<210){
                        enemySprite[planeType][t].forwardDiagDown(enemySprite[planeType][t], enemySpeed);
                    }else if(waveTime<260){
                        enemySprite[planeType][t].forwardDiagUp(enemySprite[planeType][t], enemySpeed);
                    }                    
                }
            }
            if(waveTime>259 && waveTime<399){
                enemySprite[planeType][t].forward(enemySprite[planeType][t], enemySpeed);
            }
        }

        if(waveTime>399){
            for(int t=0; t<5; t++){
                if(enemySprite[planeType][t].getX()>100){
                    enemySprite[planeType][t].forward(enemySprite[planeType][t], enemySpeed);
                }else{
                    enemySprite[planeType][t].forwardDiagDown(enemySprite[planeType][t], enemySpeed);
                }
                t++;
            }
            for(int t=1; t<5; t++){
                if(enemySprite[planeType][t].getX()>100){
                    enemySprite[planeType][t].forward(enemySprite[planeType][t], enemySpeed);
                }else{
                    enemySprite[planeType][t].forwardDiagUp(enemySprite[planeType][t], enemySpeed);
                }
                t++;
            }
        }
        
        marginHide();
        
    }

    private void visible(){
        for(int t=0; t<5; t++){
            enemySprite[0][t].setVisible(true);
        }
    }

    private void marginHide(){
         for(int i=0; i<3; i++){
            for(int t=0; t<5; t++){
                if(enemySprite[i][t].getX()<4){
                    enemySprite[i][t].setVisible(false);
                }
            }
        }
    }

    public Sprite getEnemySprite(int i, int t){
        return enemySprite[i][t];
    }

     public void checkForCollision() {
        for(int i=0; i<3; i++){
            for(int t=0; t<5; t++){
                for(int b=0; b<60; b++){
                    fBulletSprite[b] = FighterBulletSprite.getFBulletSprite(b);
                    if (enemySprite[i][t].collidesWith(fBulletSprite[b], true)) {
                        enemyX = enemySprite[i][t].getX();
                        enemyY = enemySprite[i][t].getY();
                        fBulletSprite[b].setPosition(-10,-10);
                        manager.remove(fBulletSprite[b]);                       

                        //dependent on type, score and/or remove
                        switch(i){
                            case 0:
                                parent.score = parent.score + 100;
                                removeSprite(i,t);                                               
                                break;
                            case 1:
                                parent.score = parent.score + 100;
                                enemyHits[1]++;
                                if(enemyHits[1] == 3){
                                    removeSprite(i,t);
                                    enemyHits[1] = 0;
                                    parent.score = parent.score + 100;
                                }
                                break;
                            case 2:
                                parent.score = parent.score + 100;
                                enemyHits[2]++;
                                if(enemyHits[2] == 12){
                                     removeSprite(i,t);
                                     enemyHits[2] = 0;
                                     parent.score = parent.score + 100;
                                     bonus();
                                }
                                break;
                        }
                    }
                }
            }
        }
     }

    public void bonus(){
        bonusSprite = new Sprite(bonusImage, 14, 14);
        bonusSprite.defineReferencePixel(7, 7);
        bonusSprite.setPosition(137, 80);
        manager.insert(bonusSprite, 0);        
    }

    private void moveBonus(){
         bonusX = bonusSprite.getX() - 1;
         bonusSprite.setPosition(bonusX, bonusSprite.getY());
    
    }

    public Sprite getBonusSprite(){
        return bonusSprite;
    }
    private void removeSprite(int i, int t){
                             manager.remove(enemySprite[i][t]);
                            enemySprite[i][t].setPosition(-50, -50);
                            manager.remove(enemySprite[i][t]);

                            //add explosion and
                            expSprite[i][t] = new Sprite(expImage, 20,20);
                            expSprite[i][t].defineReferencePixel(1, 8);
                            expSprite[i][t].setPosition(enemyX, enemyY);
                            manager.insert(expSprite[i][t], 0);
                            expFrame[i][t] = 0;
    }

    public void checkExp(){
        
        for(int i=0; i<3; i++){
            for(int t=0; t<5; t++){
                if(expFrame[i][t] < 16){

                    expSprite[i][t].nextFrame();
                    expFrame[i][t] ++;
             
                }
                if(expFrame[i][t] == 16){
                    manager.remove(expSprite[i][t]);
                }
            }
        }       
    }

    public Sprite getExpSprite(int i, int t){
        return expSprite[i][t];
    }
}
